"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
// 装饰器需要在tsconfig.json中加入experimentalDecorators": true 来支持装饰器
// 关于类继承
// 第一种情况，super作为函数调用时，代表父类的构造函数。(只能在constructor中存在)
// 第二种情况，super作为对象时，在普通方法中，指向父类的原型对象；在静态方法中，指向父类。
// 1.类的定义
// class Person{
//     name133:string;
//     getName():void{
//         console.log(this.name133);
//     }
// }
// let p1 = new Person();
// p1.name133 = 'ikki';
// p1.getName();
// 2.存取器
// class User {
//     myname:string;
//     constructor(myname: string) {
//         this.myname = myname;
//     }
//     get name() {
//         return this.myname;
//     }
//     set name(value) {
//         this.myname = value;
//     }
// }
// let user = new User('ikki');
// user.name = 'jiagou'; 
// console.log(user.name); 
// 编译后
// "use strict";
// var User = /** @class */ (function () {
//     function User(myname) {
//         this.myname = myname;
//     }
//     Object.defineProperty(User.prototype, "name", {
//         get: function () {
//             return this.myname;
//         },
//         set: function (value) {
//             this.myname = value;
//         },
//         enumerable: true,
//         configurable: true
//     });
//     return User;
// }());
// var user = new User('ikki');
// user.name = 'jiagou';
// console.log(user.name);
// 3.参数属性
// class User {
//     constructor(public myname: string) {}
//     get name() {
//         return this.myname;
//     }
//     set name(value) {
//         this.myname = value;
//     }
// }
// let user = new User('ikki');
// console.log(user.name); 
// user.name = 'jiagou'; 
// console.log(user.name);
// 4.readonly
// readonly修饰的变量只能在构造函数中初始化
// 在 TypeScript 中，const 是常量标志符，其值不能被重新分配
// TypeScript 的类型系统同样也允许将 interface、type、 class 上的属性标识为 readonly
// readonly 实际上只是在编译阶段进行代码检查。而 const 则会在运行时检查（在支持 const 语法的 JavaScript 运行时环境中）
// class Animal {
//     public readonly name: string
//     constructor(name:string) {
//         this.name = name;
//     }
//     changeName(name:string){
//         this.name = name;
//     }
// }
// let a = new Animal('ikki');
// a.changeName('jiagou');
// 5.继承
// class Person {
//     name: string;//定义实例的属性，默认省略public修饰符
//     age: number;
//     constructor(name:string,age:number) {//构造函数
//         this.name=name;
//         this.age=age;
//     }
//     getName():string {
//         return this.name;
//     }
//     setName(name:string): void{
//         this.name=name;
//     }
// }
// class Student extends Person{
//     no: number;
//     constructor(name:string,age:number,no:number) {
//         super(name,age);
//         this.no=no;
//     }
//     getNo():number {
//         return this.no;
//     }
// }
// let s1=new Student('zfpx',10,1);
// console.log(s1);
// 6.类里面的修饰符
// class Father {
//     public name: string;  //类里面 子类 其它任何地方外边都可以访问
//     protected age: number; //类里面 子类 都可以访问,其它任何地方不能访问
//     private money: number; //类里面可以访问， 子类和其它任何地方都不可以访问
//     constructor(name:string,age:number,money:number) {//构造函数
//         this.name=name;
//         this.age=age;
//         this.money=money;
//     }
//     getName():string {
//         return this.name;
//     }
//     setName(name:string): void{
//         this.name=name;
//     }
// }
// class Child extends Father{
//     constructor(name:string,age:number,money:number) {
//         super(name,age,money);
//     }
//     desc() {
//         console.log(`${this.name} ${this.age} ${this.money}`); //报错 属性“money”为私有属性，只能在类“Father”中访问。ts(2341)
//     }
// }
// let child = new Child('zfpx',10,1000);
// console.log(child.name);
// console.log(child.age); //报错
// console.log(child.money); //报错 属性“money”为私有属性，只能在类“Father”中访问。ts(2341)
// 7.静态属性 静态方法
// class Father {
//     static className='Father';
//     static getClassName() {
//         return Father.className;
//     }
//     public name: string;
//     constructor(name:string) {//构造函数
//         this.name=name;
//     }
// }
// console.log(Father.className);
// console.log(Father.getClassName());
// 8.装饰器
// 装饰器是一种特殊类型的声明，它能够被附加到类声明、方法、属性或参数上，可以修改类的行为
// 常见的装饰器有类装饰器、属性装饰器、方法装饰器和参数装饰器
// 装饰器的写法分为普通装饰器和装饰器工厂
// 8.1类装饰器
var a;
(function (a) {
    function addNameEat(constructor) {
        constructor.prototype.name = 'ikki';
        constructor.prototype.eat = function () { };
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person = __decorate([
            addNameEat
        ], Person);
        return Person;
    }());
    var p = new Person();
    console.log(p.name);
    p.eat();
})(a || (a = {}));
// 类的替换
var c;
(function (c) {
    //还可以替换类,不过替换的类要与原类结构相同
    function enhancer(constructor) {
        return /** @class */ (function () {
            function class_1() {
                this.name = "jiagou";
            }
            class_1.prototype.eat = function () {
                console.log("吃饭饭");
            };
            return class_1;
        }());
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person = __decorate([
            enhancer
        ], Person);
        return Person;
    }());
    var p = new Person();
    console.log(p.name);
    p.eat();
})(c || (c = {}));
// 8.2属性装饰器
// 第一个参数对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
// 第二个参数是属性的名称
(function (c) {
    function upperCase(target, propertyKey) {
        var value = target[propertyKey];
        var getter = function () {
            return value;
        };
        // 用来替换的setter
        var setter = function (newVal) {
            value = newVal.toUpperCase();
        };
        // 替换属性，先删除原先的属性，再重新定义属性
        if (delete target[propertyKey]) {
            Object.defineProperty(target, propertyKey, {
                get: getter,
                set: setter,
                enumerable: true,
                configurable: true
            });
        }
    }
    var Person = /** @class */ (function () {
        function Person() {
            this.name = 'ikki';
        }
        __decorate([
            upperCase
        ], Person.prototype, "name", void 0);
        return Person;
    }());
    var p = new Person();
    console.log(p.name);
})(c || (c = {}));
// 8.3方法装饰器
var d;
(function (d) {
    function noEnumerable(target, property, descriptor) {
        console.log('target.getName', target.getName);
        console.log('target.getAge', target.getAge);
        descriptor.enumerable = true;
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person.prototype.getName = function () {
            console.log('haha');
        };
        __decorate([
            noEnumerable
        ], Person.prototype, "getName", null);
        return Person;
    }());
    var p = new Person();
    console.log(p.getName());
})(d || (d = {}));
// 8.4参数装饰器 会在运行时当作函数被调用，可以使用参数装饰器为类的原型增加一些元数据
// 第1个参数对于静态成员是类的构造函数，对于实例成员是类的原型对象
// 第2个参数的名称
// 第3个参数在函数列表中的索引
var e;
(function (e) {
    function addAge(target, methodName, paramsIndex) {
        console.log(target);
        console.log(methodName);
        console.log(paramsIndex);
        target.age = 10;
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person.prototype.login = function (username, password) {
            console.log(this.age, username, password);
        };
        __decorate([
            __param(1, addAge)
        ], Person.prototype, "login", null);
        return Person;
    }());
    var p = new Person();
    p.login('ikki', '123456');
})(e || (e = {}));
// 8.5装饰器工厂：就是高阶函数
var b;
(function (b) {
    function addNameEatFactory(name) {
        return function addNameEat(target) {
            target.prototype.name = 'ikki' + name;
            target.prototype.eat = function () { };
        };
    }
    var Person = /** @class */ (function () {
        function Person() {
        }
        Person = __decorate([
            addNameEatFactory('真棒')
        ], Person);
        return Person;
    }());
    var p = new Person();
    console.log(p.name);
    p.eat();
})(b || (b = {}));
// 8.6装饰器执行顺序
// 类装饰器总是最后执行,而且从书写顺序自下向上
// 方法和方法参数中参数装饰器先执行。从最后一个参数依次向前执行
// 方法和属性装饰器，谁在前面谁先执行。因为参数属于方法一部分，所以参数会一直紧紧挨着方法执行
